#include <string.h>
#include <iostream>

using std::cout;
using std::endl;

//需求：只能创建堆对象,不能创建栈对象
//解决方案：将析构函数设置为私有的

class Student
{
public:
    Student(int id, const char *name)
    : _id(id)
    , _name(new char[strlen(name) + 1]())
    {
        cout << "Student(int, const char *)" << endl;
        strcpy(_name, name);
    }

    static void *operator new(size_t sz)
    {
        cout << "void *operator new(size_t )" << endl;

        /* printf("this : %p\n", this);//error */
        //申请的原始的未初始化的空间
        void *pret = malloc(sz);

        return pret;
    }

    static void operator delete(void *ptr)
    {
        cout << "void operator delete(void *)" <<endl;

        free(ptr);
    }

    void print() const
    {
        if(_name)
        {
            cout << "id = " << _id << endl
                 << "name = " << _name << endl;
        }
    }

    void destroy()
    {
        /* this->~Student();//显示调用析构函数 */
        delete this;
    }
private:
    ~Student()
    {
        cout << "~Student()" <<endl;
        /* delete this;//error */
        if(_name)
        {
            delete [] _name;
            _name = nullptr;
        }
    }
private:
    int _id;
    char *_name;
};

int main(int argc, char **argv)
{
    //Q:创建栈对象的条件有哪些？
    //A:构造函数与析构函数都需要设置为public
    /* Student stu(1234, "xiaogang");//error,栈对象 */
    /* stu.print(); */

    Student *pstu = new Student(4201, "xiaohong");//堆对象,ok
    pstu->print();

    //Q:对象的销毁与析构函数的执行是不是等价呢？
    //A:对于堆对象而言，对象的销毁会执行析构函数，但是析构函数
    //的执行只是对象销毁中的一个步骤
    //如果是栈对象，那么对象的销毁与析构函数的执行就是等价的
    /* delete pstu; */
    /* pstu = nullptr; */
    pstu->destroy();

    return 0;
}

